# 导入Request请求对象
from starlette.requests import Request

# 导入各种响应类型
from starlette.responses import (
    JSONResponse,  # JSON响应
    HTMLResponse,  # HTML响应
    PlainTextResponse,  # 纯文本响应
    RedirectResponse,  # 重定向响应
    StreamingResponse,  # 流式响应
    FileResponse,  # 文件响应
)

# 导入异步IO模块
import asyncio
import tempfile
import os


# 定义用户详情处理函数，支持GET和POST方法
async def user_detail(request: Request):
    # 从路径参数中获取用户ID
    user_id = request.path_params["user_id"]

    # 打印调试信息：请求方法和用户ID
    print(f"DEBUG: 请求方法 = {request.method}, 用户ID = {user_id}")

    # 判断请求方法是否为GET
    if request.method == "GET":
        # 处理GET请求，返回用户基本信息
        print("DEBUG: 处理GET请求")
        return JSONResponse(
            {"user_id": user_id, "method": "GET", "message": "获取用户信息成功"}
        )
    # 判断请求方法是否为POST
    elif request.method == "POST":
        # 处理POST请求，尝试解析请求体
        print("DEBUG: 处理POST请求")
        try:
            # 尝试解析JSON格式的请求体
            data = await request.json()
            # 打印解析到的JSON数据
            print(f"DEBUG: JSON数据 = {data}")
            # 返回包含数据的JSON响应
            return JSONResponse(
                {
                    "user_id": user_id,
                    "method": "POST",
                    "data": data,
                    "message": "用户数据更新成功",
                }
            )
        except Exception as e:
            # JSON解析失败，打印异常信息
            print(f"DEBUG: JSON解析失败 = {e}")
            try:
                # 尝试解析表单数据
                form_data = await request.form()
                # 打印解析到的表单数据
                print(f"DEBUG: 表单数据 = {dict(form_data)}")
                # 返回包含表单数据的JSON响应
                return JSONResponse(
                    {
                        "user_id": user_id,
                        "method": "POST",
                        "form_data": dict(form_data),
                        "message": "表单数据接收成功",
                    }
                )
            except Exception as e2:
                # 表单解析也失败，打印异常信息
                print(f"DEBUG: 表单解析失败 = {e2}")
                # 返回错误信息，提示无法解析请求数据
                return JSONResponse(
                    {
                        "user_id": user_id,
                        "method": "POST",
                        "error": "无法解析请求数据",
                        "message": "请发送有效的JSON或表单数据",
                    },
                    status_code=400,
                )
    else:
        # 处理不支持的请求方法
        print(f"DEBUG: 不支持的请求方法 = {request.method}")
        # 返回405错误，提示只允许GET和POST
        return JSONResponse(
            {"error": "不支持的请求方法", "allowed_methods": ["GET", "POST"]},
            status_code=405,
        )


# 定义HTML响应函数
async def html_response(request: Request):
    # 构造HTML内容，包含当前时间、请求路径和方法
    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>HTML响应测试</title>
    </head>
    <body>
        <h1>这是一个HTML响应</h1>
        <p>当前时间: {}</p>
        <p>请求路径: {}</p>
        <p>请求方法: {}</p>
    </body>
    </html>
    """.format(
        asyncio.get_event_loop().time(), request.url.path, request.method
    )
    # 返回HTML响应
    return HTMLResponse(html_content)


# 定义纯文本响应函数
async def text_response(request: Request):
    # 构造多行纯文本内容，包含时间、路径、方法和用户代理
    text_content = f"""
纯文本响应示例
================

当前时间: {asyncio.get_event_loop().time()}
请求路径: {request.url.path}
请求方法: {request.method}
用户代理: {request.headers.get('user-agent', '未知')}

这是一个多行文本响应，用于测试PlainTextResponse。
    """.strip()
    # 返回纯文本响应
    return PlainTextResponse(text_content)


# 定义重定向响应函数
async def redirect_response(request: Request):
    # 返回重定向响应，跳转到静态文件页面
    return RedirectResponse(url="/static/test_all.html")


# 定义流式数据响应函数
async def stream_data(request: Request):
    # 定义异步生成器函数，用于逐条生成数据
    async def generate():
        # 循环生成10条数据
        for i in range(10):
            # 生成一行数据
            yield f"data: {i}\n\n"
            # 每次等待1秒
            await asyncio.sleep(1)

    # 返回流式响应，媒体类型为text/plain
    return StreamingResponse(generate(), media_type="text/plain")


# 定义文件响应函数
async def file_response(request: Request):
    # 创建临时文件，写入测试内容
    with tempfile.NamedTemporaryFile(
        mode="w", suffix=".txt", delete=False, encoding="utf-8"
    ) as f:
        # 写入多行内容
        f.write("这是一个测试文件\n")
        f.write("包含多行内容\n")
        f.write("用于测试FileResponse\n")
        f.write(f"创建时间: {asyncio.get_event_loop().time()}\n")
        f.write("文件内容结束\n")
        # 获取临时文件路径
        temp_file_path = f.name

    # 返回文件响应，设置下载文件名和媒体类型
    return FileResponse(
        path=temp_file_path,
        filename="test_file.txt",
        media_type="text/plain",
        headers={"Content-Disposition": "attachment; filename=test_file.txt"},
    )


# 定义表单处理函数
async def form_handler(request: Request):
    # 判断请求方法是否为POST
    if request.method == "POST":
        # 解析表单数据
        form_data = await request.form()
        # 返回表单数据的JSON响应
        return JSONResponse({"message": "表单提交成功", "form_data": dict(form_data)})
    else:
        # 构造HTML表单页面
        html_form = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>表单测试</title>
        </head>
        <body>
            <h1>表单测试</h1>
            <form method="POST">
                <label>姓名: <input type="text" name="name" required></label><br><br>
                <label>邮箱: <input type="email" name="email" required></label><br><br>
                <label>消息: <textarea name="message" rows="4" cols="50"></textarea></label><br><br>
                <button type="submit">提交</button>
            </form>
        </body>
        </html>
        """
        # 返回HTML响应
        return HTMLResponse(html_form)


# 定义主函数，启动Starlette应用
def main():
    # 导入Starlette相关模块
    from starlette.applications import Starlette
    from starlette.routing import Route, Mount
    from starlette.staticfiles import StaticFiles
    import uvicorn

    # 创建Starlette应用实例，配置路由
    app = Starlette(
        routes=[
            # 用户详情接口，支持GET和POST
            Route("/users/{user_id:int}", user_detail, methods=["GET", "POST"]),
            # HTML响应接口
            Route("/html", html_response),
            # 纯文本响应接口
            Route("/text", text_response),
            # 重定向接口
            Route("/redirect", redirect_response),
            # 流式响应接口
            Route("/stream", stream_data),
            # 文件下载接口
            Route("/file", file_response),
            # 表单处理接口
            Route("/form", form_handler),
            # 挂载静态文件目录
            Mount("/static", app=StaticFiles(directory="static"), name="static"),
        ]
    )

    # 打印服务器启动信息和可用端点
    print(" 服务器启动中...")
    print("📱 访问地址: http://127.0.0.1:8000")
    print("🧪 测试页面: http://127.0.0.1:8000/static/test_all.html")
    print(" 可用端点:")
    print("   - GET  /users/{user_id} - 用户详情")
    print("   - GET  /html - HTML响应")
    print("   - GET  /text - 纯文本响应")
    print("   - GET  /redirect - 重定向响应")
    print("   - GET  /stream - 流式响应")
    print("   - GET  /file - 文件下载")
    print("   - GET/POST /form - 表单处理")
    print("   - GET  /static/* - 静态文件")

    # 启动uvicorn服务器，监听127.0.0.1:8000
    uvicorn.run(app, host="127.0.0.1", port=8000)


# 判断是否为主模块，作为脚本入口
if __name__ == "__main__":
    main()
